﻿using System;
using System.Linq;
using iss.sg4210.se18.team6s.jass.DAL;
using iss.sg4210.se18.team6s.jass.DAL.DataAccess.Interfaces;

namespace iss.sg4210.se18.team6s.jass.BL
{
    public class ResponsesFacade
    {
        IResponse responseRepo = null;
        IResponseActions responseActionRepo = null;
        IActions actionRepo = null;

        public ResponsesFacade()
        {
            responseRepo = DataAccessFactory.Instance.Response;
            responseActionRepo = DataAccessFactory.Instance.ResponseAction;
            actionRepo = DataAccessFactory.Instance.Action;
        }

        #region Response
        public void AddResponse(Response response)
        {
            //check if the person has already responded
            if (HasAlreadyResponded(response))
                throw new JASSException("You have already responded to this Job Advertisement!");

            try
            {
                //then add
                responseRepo.AddResponse(response);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_SAVE, ex);
            }
        }

        public Response GetResponseById(int id)
        {
            try
            {
                return responseRepo.GetResponse(id);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public IQueryable<Response> FindAllResponsesByUser(Guid userId)
        {
            try
            {
                return responseRepo.FindAllResponsesByUser(userId);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public IQueryable<Response> FindAllResponsesByAdvertisement(Guid advertiserId)
        {
            try
            {
                IQueryable<Response> responses = FindAllResponses();
                return responses.Where(m => m.Advertisement.UserId == advertiserId);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public void UpdateResponse(Response response)
        {
            try
            {
                responseRepo.UpdateResponse(response);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_UPDATE, ex);
            }
        }

        private bool HasAlreadyResponded(Response response)
        {
            return responseRepo.FindAllResponsesByUser(response.UserId).Any(m => m.AdvertisementId == response.AdvertisementId);
        }

        public void DeleteResponse(int id)
        {
            try
            {
                responseRepo.DeleteResponse(id);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_DELETE, ex);
            }
        }

        public IQueryable<Response> FindAllResponses()
        {
            try
            {
                return responseRepo.FindAllResponses();
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public Response GetResponse(int id)
        {
            try
            {
                return responseRepo.GetResponse(id);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }
        #endregion

        #region ResponseAction
        public IQueryable<ResponseAction> FindAllResponseActions()
        {
            try
            {
                return responseActionRepo.FindAllResponseActions();
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public object FindAllResponsesActionsByAdvertisement(Guid advertiserId)
        {
            try
            {
                IQueryable<ResponseAction> responseActions = FindAllResponseActions();
                return responseActions.Where(m => m.Response.Advertisement.UserId == advertiserId);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public void DeleteResponseAction(int id)
        {
            try
            {
                responseActionRepo.DeleteResponseAction(id);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_DELETE, ex);
            }
        }

        public ResponseAction GetResponseAction(int id)
        {
            try
            {
                return responseActionRepo.GetResponseAction(id);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public object GetResponseAction(int id, Guid advertiserId)
        {
            ResponseAction responseAction = GetResponseAction(id);
            if (responseAction.Response.Advertisement.UserId != advertiserId)
                throw new JASSException("You are not authorised to view this Response Action!");

            try
            {
                return responseAction;
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public void UpdateResponseAction(ResponseAction responseAction)
        {
            try
            {
                responseActionRepo.UpdateResponseAction(responseAction);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_UPDATE, ex);
            }
        }

        public void AddResponseAction(ResponseAction responseAction)
        {
            try
            {
                responseActionRepo.AddResponseAction(responseAction);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_SAVE, ex);
            }
        }
        #endregion

        #region Action
        public void DeleteAction(int id)
        {
            try
            {
                actionRepo.DeleteAction(id);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_DELETE, ex);
            }
        }

        public DAL.Action GetAction(int id)
        {
            try
            {
                return actionRepo.GetAction(id);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }

        public void UpdateAction(DAL.Action action)
        {
            try
            {
                actionRepo.UpdateAction(action);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_UPDATE, ex);
            }
        }

        public void AddAction(DAL.Action action)
        {
            IQueryable<DAL.Action> actions = FindAllActions();
            if (actions.Count(m => m.Name == action.Name) > 0)
                throw new JASSException("Duplicate Action with same Title '" + action.Name + "' found!");
            try
            {
                actionRepo.AddAction(action);
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_SAVE, ex);
            }
        }

        public IQueryable<DAL.Action> FindAllActions()
        {
            try
            {
                return actionRepo.FindAllActions();
            }
            catch (Exception ex)
            {
                throw new JASSException(JASSConstants.JASS_ERROR_RETRIEVE, ex);
            }
        }
        #endregion

    }
}
